#region Imported Namespaces
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using BO = PHSRAG.Insight21.BusinessObjects;
using DataAccess = PHSRAG.Utility.DataAccess;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using PHSRAG.Insight21.InsightUtilities;
using GenerateKey = PHSRAG.Insight21.BusinessObjects.ModuleKey;
#endregion

namespace PHSRAG.Insight21.Admin
{
	/// <summary>
	/// Business object that handles retrievals of labs based on search criteria and
	/// lab deletions. It also handles caching and uncaching of this object.
	/// </summary>
	public class Labs : BO.SaveableBusinessObject
	{
		#region Constants
		/// <summary>Key used for caching labs.</summary>
		private static string LabsKey = GenerateKey.MakeKey("Labs_F4658030-E91E-4687-AF43-225978F8BDF9",GenerateKey.Admin);
		/// <summary>The name of the table with lab rows.</summary>
		private const string LabTableName = "Labs";
		#endregion

		#region Instance Variables
		private SqlCommand deleteLabCommand;
		#endregion

		#region Constructor
		/// <summary>
		/// Initializes the data container.
		/// </summary>
		/// <param name="cachePolicy">The polisy to be used for cacheing.</param>
		public Labs(ICachePolicy cachePolicy) : base(cachePolicy)
		{
			DataContainer = new DataSet();
		}
		#endregion

		#region Public Properties
		/// <summary>
		/// Gets lab DataTable from this object's data container.
		/// </summary>
		public DataTable LabsDataTable
		{
			get { return DataContainer.Tables[LabTableName]; }
		}
		#endregion

		#region BusinessObject Methods
		/// <summary>Caches thhis object based on it's caching policy.</summary>
		public override void Cache()
		{
			CachePolicy.Cache(LabsKey, this);
		}

		/// <summary>UnCaches this object based on it's caching policy.</summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(LabsKey);
		}

		/// <summary>
		/// Invokes GetAdminLab stored procedure and sets the datacontainer with the resultset. 
		/// </summary>
		/// <param name="connectionString">A valid database connection string.</param>
		/// <param name="args">Lab Name, PI Username, PI Last Name, PI First Name, and OrganizationId</param>
		public override void Load(string connectionString, params object[] args)
		{
			try 
			{
				if (args.Length != 5)
					throw new Exception("Lab Name, PI Username, PI Last Name, PI First Name, and OrganizationId must be provided.");

				DataAccess.LoadDataSet(DataContainer, LabTableName, connectionString, "GetAdminLabs",
					DataAccess.BuildSqlParameterArray("@labName", SqlDbType.VarChar, args[(int)LoadLabsParameters.LabName],
					"@piUsername", SqlDbType.VarChar, args[(int)LoadLabsParameters.PIUserName],
					"@piLastName", SqlDbType.VarChar, args[(int)LoadLabsParameters.PILastName],
					"@piFirstName", SqlDbType.VarChar, args[(int)LoadLabsParameters.PIFirstName],
					"@organizationId", SqlDbType.Int, args[(int)LoadLabsParameters.OrganizationID]));
			}
			catch( Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog ("Labs Load", e, true, Utility.ExceptionReport.ReportType.Error);
			}
		}

		/// <summary>
		/// Persists all changed made to the lab dataset to the database.
		/// </summary>
		/// <param name="connectionString">A valid database connection string.</param>
		/// <param name="args">No additional params needed.</param>
		public override void Save(string connectionString, params object[] args)
		{
//			connectionString = string.Format("{0} Connect Timeout={1};", connectionString, Utility.Settings.GetKeyValue("Database.Insight.CommandTimeout", "0")); 
			SqlConnection connection = new SqlConnection(connectionString);
			try
			{
				connection.Open();
				CreateCommands();
				ExecuteLabDelete(connection);
			}
			finally
			{
				if (connection.State != ConnectionState.Closed)
					connection.Close();
			}
		}

		#endregion

		#region Private Methods
		/// <summary>
		/// Create the set of SqlCommand objects used for the deletion, and updates made on
		/// the associated DataTable. Notice that each command is initialized to invoke a stored
		/// procedure implying that each command may have its own set of parameters in line with that
		/// stored procedure.
		/// </summary>
		private void CreateCommands()
		{
			deleteLabCommand = new SqlCommand();
			deleteLabCommand.CommandText = "DeleteAdminLab";
			deleteLabCommand.CommandTimeout = Convert.ToInt32(Utility.Settings.GetKeyValue("Database.Insight.CommandTimeout", "0"));
			deleteLabCommand.CommandType = CommandType.StoredProcedure;
			deleteLabCommand.CommandTimeout = Convert.ToInt32(Utility.Settings.GetKeyValue("Database.Insight.CommandTimeout", "0"));
			((SqlParameter)deleteLabCommand.Parameters.Add("@labID", SqlDbType.Int)).SourceColumn = "Id";
		}

		/// <summary>
		/// This method is invoked to carry out deletion of one or more rows from
		/// the Lab DataTable. Nothing is done if there are no rows marked for deletion within the
		/// DataTable.
		/// </summary>
		/// <param name="connection">An instance of an open connection to the database</param>
		private void ExecuteLabDelete(SqlConnection connection)
		{
			SqlDataAdapter adapter = new SqlDataAdapter();
			deleteLabCommand.Connection = connection;				
			adapter.DeleteCommand = deleteLabCommand;
			adapter.Update(DataContainer, LabTableName);
		}
		#endregion
	}
	/// <summary>
	/// Represent the positions of Labs Load methods parameters. 
	/// </summary>
	public enum LoadLabsParameters 
	{
		LabName, PIUserName, PILastName, PIFirstName, OrganizationID
	}
}
